<template>
  <div class="data-mapping-table">
    <!-- xtag数据接口未通，为sit转测临时修改 -->
    <VsFormItem
      v-if="[xMiner, xTag].includes(form.dataSourceType) && !curComp"
      class="isExport"
      :label="$demoi18n('panel.button.exportData')"
    >
      <el-switch v-model="form.isExport"></el-switch>
    </VsFormItem>

    <el-button
      size="default"
      class="btn-sure"
      icon="CirclePlus"
      :disabled="isDimension ? addDimensionDisable : addDisable"
      @click.stop="isDimension ? addDimension() : addNewRow()"
    >{{ isDimension ? $demoi18n('btn.add.Dimension') : $demoi18n('btn.add') }}</el-button>
    <el-table
      ref="table"
      class="config-panel-table mapping-table"
      :data="form.tableData"
      style="width: 100%"
      max-height="240"
      size="default"
      :tooltip-effect="xvueTheme"
    >
      <el-table-column
        v-if="!isDimension"
        type="index"
        :label="$demoi18n('panel.th.number')"
        :width="40"
      ></el-table-column>
      <el-table-column
        v-else
        prop="index"
        :label="$demoi18n('panel.th.number')"
        :width="40"
      ></el-table-column>
      <el-table-column
        :label="$demoi18n('panel.th.fieldName')"
        min-width="70"
        :render-header="renderTableHeader"
      >
        <template #default="scope">
          <span
            v-if="!scope.row.skipVerification"
            class="mapping-scope"
          >*</span>
          <VsFormItem
            :prop="`tableData[${scope.$index}].mapping`"
            :rules="
              generateExceptionRules({
                required: !scope.row.skipVerification,
                label: $demoi18n(scope.row.explain),
              })
            "
          >
            <!-- xTag 下拉项 -->
            <el-select
              v-if="form.dataSourceType === 'xTag'"
              v-model="scope.row.mapping"
              :class="'panel-data-select-' + xvueTheme"
              :popper-class="'select-poper-' + xvueTheme"
              filterable
              clearable
              placeholder
              size="default"
              @focus="setXtagMaxWidth"
              @visible-change="setTagTitle($event)"
              @change="xTagTableDataChange(scope.row)"
            >
              <el-option
                v-for="(item, index) in commonComp.mappingOptionsXTag"
                :key="item.id"
                class="panel-data-select-option"
                :label="item.option_label"
                :value="item.option_label"
                :style="selectxTagStyle"
              >
                <div
                  v-if="item.type && item.type === 'add'"
                  @click.stop="optionxTagClick(item, scope.row, 'fromChild')"
                >
                  <span class="select-option-slot-icon">
                    <el-button
                      type="primary"
                      :link="true"
                      class="select-icon"
                    >
                      <el-icon><Plus /></el-icon>
                    </el-button>
                  </span>
                  <span
                    class="select-option-slot-text"
                    :style="{ width: `${xTagTextWidth}px` }"
                  >&nbsp;{{ item.option_label }}</span>
                </div>
                <div v-else-if="item.type && item.type === 'edit'">
                  <span class="select-option-slot-icon select-option-slot-icon-edit">
                    <el-button
                      type="primary"
                      :link="true"
                      class="select-icon"
                      :title="$demoi18n('btn.edit')"
                      @click.stop="optionxTagClick(item, scope.row, 'fromChild')"
                    >
                      <el-icon><EditPen /></el-icon>
                    </el-button>
                    <el-button
                      type="primary"
                      :link="true"
                      class="select-icon"
                      :title="$demoi18n('btn.delete')"
                      @click.stop="optionxTagDelete(index)"
                    >
                      <el-icon><Delete /></el-icon>
                    </el-button>
                  </span>
                  <span
                    class="select-option-slot-text"
                    :style="{ width: `${xTagTextWidth}px` }"
                  >{{
                    item.option_label
                  }}</span>
                </div>
                <div v-else>
                  <span>{{ item.option_label }}</span>
                </div>
              </el-option>
            </el-select>
            <!-- xMiner 下拉项 -->
            <el-select
              v-else
              v-model="scope.row.mapping"
              :class="'panel-data-select-' + xvueTheme"
              :popper-class="'select-poper-' + xvueTheme"
              filterable
              clearable
              placeholder
              size="default"
              @focus="setMaxWidth"
              @visible-change="setTagTitle($event)"
              @change="getTableApiData(scope.row)"
            >
              <el-option
                v-for="item in commonComp.mappingOptions"
                :key="item.id"
                class="panel-data-select-option"
                :label="item.option_label"
                :value="item.option_value"
                :style="selectStyle"
              >
                <div
                  class="vs_ellipsis"
                  :title="`${item.option_label} (${item.option_value})`"
                >{{ item.option_label }}</div>
              </el-option>
            </el-select>
          </VsFormItem>
        </template>
      </el-table-column>

      <el-table-column
        prop="field"
        :label="$demoi18n('panel.th.aliasName')"
        min-width="70"
        :render-header="renderTableHeader"
      >
        <template #default="scope">
          <VsFormItem
            v-if="isDimensionTable(scope.row)"
            :prop="`tableData[${scope.$index}].field`"
            :rules="
              generateExceptionRules({
                required: false,
                label: $demoi18n(scope.row.explain),
              })
            "
          >
            <el-input
              v-model="scope.row.field"
              size="default"
              :placeholder="$demoi18n('panel.label.aliasNoRepeat')"
            ></el-input>
          </VsFormItem>
        </template>
      </el-table-column>

      <el-table-column
        v-if="!dataForm.widthHidden"
        prop="width"
        :label="$demoi18n('panel.label.widthPx')"
        min-width="70"
        :render-header="renderTableHeader"
      >
        <template #default="scope">
          <VsFormItem>
            <el-input-number
              v-model="scope.row.width"
              style="width:100%"
              size="default"
              :controls="false"
            ></el-input-number>
          </VsFormItem>
        </template>
      </el-table-column>

      <el-table-column
        v-if="isShowFieldType"
        prop="type"
        :label="$demoi18n('panel.label.fieldType')"
        min-width="70"
        :render-header="renderTableHeader"
      >
        <template #default="scope">
          <VsFormItem>
            <el-select
              v-if="isDimensionTable(scope.row)"
              v-model="scope.row.fieldType"
              placeholder
              size="default"
              @change="handleFieldTypeChange(scope.row)"
            >
              <el-option
                v-for="item in fieldTypeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              >
              </el-option>
            </el-select>
          </VsFormItem>
        </template>
      </el-table-column>
      <el-table-column
        v-if="isDimension"
        prop="explain"
        min-width="36"
        :label="$demoi18n('panel.th.explain')"
        :render-header="renderTableHeader"
        :show-overflow-tooltip="true"
      >
        <template #default="scope">
          <span>{{ $demoi18n(scope.row.explain) }}</span>
        </template>
      </el-table-column>
      <el-table-column
        :label="$demoi18n('panel.th.operation')"
        min-width="110"
        :render-header="renderTableHeader"
      >
        <template #default="scope">
          <el-button
            v-if="isDimensionTable(scope.row)"
            type="primary"
            icon="SortUp"
            :link="true"
            :disabled="scope.$index === 0"
            @click.stop="moveUp(scope.$index, scope.row)"
          ></el-button>
          <el-button
            v-if="isDimensionTable(scope.row)"
            type="primary"
            icon="SortDown"
            :link="true"
            style="margin-left: 1px;"
            :disabled="
              isDimension
                ? scope.$index === form.tableData.filter(it => it.fieldType).length - 1
                : scope.$index === form.tableData.length - 1
            "
            @click.stop="moveDown(scope.$index, scope.row)"
          ></el-button>
          <el-button
            v-if="isDimensionTable(scope.row)"
            type="primary"
            icon="Delete"
            :link="true"
            style="margin-left: 1px;"
            :disabled="isDimension ? delDimensionDisable : delDisable"
            @click.stop="isDimension ? deleteDimension(scope.row) : deleteCurRow(scope.row)"
          ></el-button>
          <el-button
            v-if="isDimensionTable(scope.row)"
            type="primary"
            icon="Setting"
            :link="true"
            style="margin-left: 1px;"
            @click.stop="handleFieldSetting(scope.row, scope.$index)"
          ></el-button>
          <div
            v-if="isDimensionTable(scope.row)"
            class="eye"
            :style="{ color: '#409EFF', marginLeft: '1px', cursor: 'pointer' }"
            @click.stop="handleVisible(scope.row, scope.$index)"
          >
            <i
              v-if="scope.row.visible"
              class="vs_icon_dev vs_icon_dev_eye"
            ></i>
            <i
              v-else
              class="vs_icon_dev vs_icon_dev_eye-off"
            ></i>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <FieldSetting
      ref="FieldSetting"
      :config="config"
      :cur-comp="curComp"
      @save="handleFieldSettingSave"
    />
  </div>
</template>
<script lang="jsx">
import { fixAdvLinkage } from '@/components/common/advanced-linkage/advanced-linkage-util.js';
import FieldSetting from '@/components/common/field-setting/field-setting';
import {
  columnItem,
  customStyle,
  fieldTypeOptions,
} from '@/components/panel-data/components/table-column-default-config';
import xTagBase from '@/components/panel-data/xtag-base.js';
import EventBus from '@/event-bus/EventBus.js';
import { clone, isEmptyObject } from '@/utils/util';
import { mapState } from 'vuex';

/**
 * config  整体配置项
 * dataForm   初始表单的字段
 */
const xMiner = 'xMiner';
const xTag = 'xTag';
const FORM_MIN = 1;
const FORM_MAX = 10000; // 不限制最大列数
export default {
  name: 'DataMappingTable',
  components: { FieldSetting },
  mixins: [xTagBase],
  props: {
    config: Object,
    widgetInstanceId: String,
    dataForm: Object,
    dataSourceTypeOptions: Array,
    commonComp: Object,
    doGetApiData: Boolean,
    curComp: String,
    isDimension: Boolean,
    isShowFieldType: { // 是否显示数据类型
      type: Boolean,
      default: true,
    },
  },
  emits: ['updateTableColumnOptions'],
  data() {
    return {
      xMiner,
      xTag,
      propertyData: this.property,
      form: {},
      fieldTypeOptions: fieldTypeOptions,
      addDisable: false,
      delDisable: false,
      upDisable: false,
      downDisable: false,
      xTagTextWidth: 100,
      addDimensionDisable: false,
      delDimensionDisable: false,
    };
  },
  computed: {
    ...mapState({
      panelConfigs: state => state.VisualComponentsModule.panelConfigs,
      panelApiData: state => state.VisualComponentsModule.panelApiData,
    }),
    panelConfig() {
      const emptyConfig = {
        siteId: '',
        widgetInstanceId: '',
        property: {},
        data: {
          tableData: [],
        },
        events: {},
      };
      return this.panelConfigs[this.widgetInstanceId] || emptyConfig;
    },
  },
  watch: {
    'form.tableData': {
      handler(val) {
        EventBus.$emit('updateTableColumnOptions', val);
      },
      deep: true,
      immediate: true,
    },
    'form.dataSourceType': {
      handler(val) {
        if (![xMiner, xTag].includes(val) && !this.curComp) {
          this.form.isExport = false;
        }
      },
    },
  },
  created() {
    this.form = this.dataForm;

    if (this.config) {
      this.initOption();
      this.initAdvLinkage();

      // 维度度量初始化数据
      if (this.isDimension) {
        this.initTableData();
      }
    }
  },
  methods: {
    initOption() {
      const count = this.form.tableData.length;
      if (count <= FORM_MIN) {
        this.delDisable = true;
      }
      if (count >= FORM_MAX) {
        this.addDisable = true;
      }
    },

    // 兼容历史跳转设置数据
    initAdvLinkage() {
      this.form.tableData.forEach(n => {
        fixAdvLinkage(n);
      });
    },
    initTableData() {
      const dimensionCount = this.form.tableData.filter(item => item.fieldType).length;
      if (dimensionCount <= FORM_MIN) {
        this.delDimensionDisable = true;
      }
      if (dimensionCount >= FORM_MAX) {
        this.addDimensionDisable = true;
      }
    },
    addDimension() {
      let addItem = {};
      const dimensionCount = this.form.tableData.filter(item => item.fieldType).length;
      if (dimensionCount >= 1) {
        addItem = {
          field: `row${dimensionCount + 1}`,
          newDimensionfield: `row${dimensionCount + 1}`,
          mapping: '',
          explain: this.$demoi18n('panel.label.dimension'),
          width: '',
          fieldType: 'string',
          uploadImgList: [],
          advancedLinkage: {
            linkageDatas: [],
          },
          style: {},
          visible: true,
          index: dimensionCount + 1,
        };
      }
      this.form.tableData.splice(dimensionCount, 0, addItem);
      const newDimensionCount = this.form.tableData.filter(item => item.fieldType).length;
      if (newDimensionCount >= FORM_MIN) {
        this.delDimensionDisable = false;
      }
      if (newDimensionCount >= FORM_MAX) {
        this.addDimensionDisable = true;
      }
    },
    deleteDimension(row) {
      const index = this.form.tableData.indexOf(row);
      this.form.tableData.splice(index, 1);
      const dimensionCount = this.form.tableData.filter(item => item.fieldType).length;
      for (let i = index; i < dimensionCount; i++) {
        this.form.tableData[i].field = `row${i + 1}`;
        this.form.tableData[i].newDimensionfield = `row${i + 1}`;
        this.form.tableData[i].index = i + 1;
      }
      if (dimensionCount <= FORM_MIN) {
        this.delDimensionDisable = true;
      }
      if (dimensionCount <= FORM_MAX) {
        this.addDimensionDisable = false;
      }
    },
    addNewRow() {
      const temp = JSON.parse(JSON.stringify(columnItem));
      if (this.dataForm.widthHidden) {
        delete temp.width;
      }
      this.form.tableData.push(temp);
      const count = this.form.tableData.length;
      if (count >= FORM_MIN) {
        this.delDisable = false;
      }
      if (count >= FORM_MAX) {
        this.addDisable = true;
      }
    },
    deleteCurRow(item) {
      const index = this.form.tableData.indexOf(item);
      this.form.tableData.splice(index, 1);
      const count = this.form.tableData.length;
      if (count <= FORM_MIN) {
        this.delDisable = true;
      }
      if (count <= FORM_MAX) {
        this.addDisable = false;
      }
    },
    moveUp(index) {
      if (index > 0) {
        const temp = this.form.tableData[index - 1];
        this.form.tableData.splice(index - 1, 1);
        this.form.tableData.splice(index, 0, temp);
      }
    },
    moveDown(index) {
      const temp = this.form.tableData[index + 1];
      this.form.tableData.splice(index + 1, 1);
      this.form.tableData.splice(index, 0, temp);
    },
    getTableApiData(row) {
      this.autoFill(row);
      this.getApiData();
    },
    autoFill(row) {
      let item = this.commonComp.mappingOptions.find(
        option => option.option_value === row.mapping || option.option_label === row.mapping,
      );

      // xTag自定义函数情况下
      if (!item) {
        item = this.commonComp.mappingOptionsXTag.find(
          option => option.option_value === row.mapping || option.option_label === row.mapping,
        );
      }
      if (this.isDimensionTable(row)) {
        row.field = item.option_label;
      }
    },
    isDimensionTable(row) {
      const isRowDimension = row.field !== 'column' && row.field !== 'value' && this.isDimension;
      if ( isRowDimension || !this.isDimension) {
        return true;
      }
      return false;
    },
    handleFieldTypeChange(row) {
      const { style } = row;
      row.style = isEmptyObject(style) ? this.chooseStyleForm(row.fieldType) : clone(style);
    },
    chooseStyleForm(fieldType) {
      let style;
      switch (fieldType) {
        case 'percentage':
          style = clone(customStyle);
          style.color = this.getValByCompStl('#00aaff', '#00f0ff', '#eee');
          break;
        case 'status':
          style = clone(customStyle);
          break;
        default:
          style = {};
          break;
      }
      return style;
    },

    // 根据主题色获取对应
    getValByCompStl(lightVal, darkVal, realVal) {
      const { componentStyle } = this.panelConfig.property;
      const map = {
        light: lightVal,
        dark: darkVal,
        real: realVal,
      };
      return map[componentStyle];
    },
    handleFieldSetting(row, index) {
      if (this.$refs.FieldSetting) {
        this.$refs.FieldSetting.openDialog(row, index);
      }
    },
    handleVisible(row, index) {
      this.form.tableData[index].visible = !row.visible;
    },
    handleFieldSettingSave(jumpObj) {
      const { fieldForm, index } = jumpObj;
      this.form.tableData[index] = clone(fieldForm);
      this.form.tableData = clone(this.form.tableData);
    },
    renderTableHeader({ column }) {
      return (
        <el-tooltip placement="top" content={column.label} effect={this.xvueTheme}>
          <span>{column.label}</span>
        </el-tooltip>
      );
    },
  },
};
</script>
<style lang="less" scoped>
:deep(.el-table) {
  .cell {
    display: flex;
    align-items: center;
    padding: 0 3px !important;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    .el-input__wrapper {
      padding: 0 5px;
    }
    .el-input__inner {
      font-size: 12px;
    }
    .el-input__suffix-inner {
      .el-select__icon {
        margin: 0;
      }
    }
    .eye {
      @height: 14px;
      display: inline-flex;
      height: @height;
      align-items: center;
      .vs_icon_dev {
        font-size: @height;
        line-height: @height;
      }
    }
    .el-form-item.is-error {
      margin-bottom: 36px !important;
    }
  }
  .el-table__body-wrapper {
    overflow: auto !important;
  }
}
.prop-form {
  :deep(.xtag-dataTable-select) {
    width: 129px;
    padding-right: 8px;
  }
  .input-number {
    width: 80px;
    :deep(.el-input-number__decrease) {
      width: 19px;
    }
    :deep(.el-input-number__increase) {
      width: 19px;
    }
    :deep(.el-input__inner) {
      padding-left: 19px;
      padding-right: 19px;
    }
  }
}
</style>

<style lang="less">
.panel-data-select-dark {
  .el-input {
    .el-input__wrapper {
      background-color: #091a2d;
    }
    .el-input__inner {
      border-color: #588ba8;
      color: #fff;
      background-color: #091a2d;
    }
    .el-input__icon {
      color: #588ba8;
    }
  }
}

.select-poper-dark {
  background-color: #091a2d;
  border-color: #588ba8;

  .el-scrollbar {
    .el-select-dropdown__list {
      .el-select-dropdown__item {
        padding: 0 12px;
        height: 24px;
        line-height: 24px;
        font-size: 12px;
        color: #83b0ca;
        background-color: #122b40;

        .select-icon {
          margin-left: 0;
          padding: 0;
        }

        .select-option-slot-text {
          display: inline-block;

          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          color: #178ddf;
        }
        .select-option-slot-icon {
          display: inline-block;
          vertical-align: top;
        }
      }
      .hover {
        background-color: #102e4f;
      }
    }
  }
  :deep(.popper__arrow) {
    border-bottom-color: #588ba8;
    &::after {
      border-bottom-color: #091a2d !important;
    }
  }
}

.select-poper-light {
  .el-scrollbar {
    .el-select-dropdown__list {
      .el-select-dropdown__item {
        padding: 0 12px;
        height: 24px;
        line-height: 24px;
        font-size: 12px;

        .select-icon {
          margin-left: 0;
          padding: 0;
        }

        .select-option-slot-text {
          display: inline-block;

          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        .select-option-slot-icon {
          display: inline-block;
          vertical-align: top;
        }
      }
    }
  }
}
</style>
